package com.bening.smsapp.parser.thread.worker;

import com.bening.smsapp.bean.*;

import com.bening.smsapp.factory.SmsAppFactory;
import com.bening.smsapp.util.SmsAppTools;

import org.apache.commons.beanutils.*;
import com.bening.smsapp.bootstrap.BootConfigParameters;
import com.bening.smsapp.constant.PropertiesConstant;
import com.bening.smsapp.constant.SmsAppConstant;
import com.bening.smsapp.dao.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;

import org.apache.log4j.Logger;

public class AsciiParserWorker 
{

	private static BootConfigParameters bootParam = BootConfigParameters.getInstance();
	final static Logger logger = Logger.getLogger( AsciiParserWorker.class );
	private static SmsAppDao smsDao = SmsAppFactory.getDaoObject();
	private static List rule = bootParam.getAsciiParserRule();
	
    public AsciiParserWorker() {
		// TODO Auto-generated constructor stub
	}

    /**
     * parse a single file, given the folder name and filename.
     * @param folder
     * @param filename
     */
    public void parseFileToDatabase( String folder, String filename , int sourcePathId)
    {
        //List fileContent = new ArrayList();
        List parseResult = new ArrayList();
        
        int lineError = 0;
        int lineNum = 0;
        
        BufferedReader reader;
        // update start processing time
        try  {
        	SmsAppTools.updateFileStatus(filename, SmsAppConstant.FLAG_PARSE_RUNNING);
        }catch(SQLException s) {
        	logger.error(s);
        	SmsAppTools.InsertEventLog(SmsAppConstant.SQL_ERROR, s.getMessage(), sourcePathId);
        }

        try
        {
            if ( logger.isInfoEnabled() )
            {
                logger.info( "Thread "+Thread.currentThread().getName()+" start parsing file: " + filename );
            }

            reader = new BufferedReader( new FileReader( folder + File.separator + filename ) );
            String currentLine = reader.readLine();
            
            while( currentLine != null )
            {
                //fileContent.add(lineNum,currentLine);
            	parseResult.add(lineNum,ParseToBean(currentLine));
                lineNum++;
                currentLine = reader.readLine();
            }
            reader.close();
            
            // parsing start
            /*for(int i=0;i<fileContent.size();i++) {
            	parseResult.add(i,ParseToBean((String)fileContent.get(i)));
            }*/
            // parsing end
            // insert result to database
            logger.info( "Thread "+Thread.currentThread().getName()+" end parsing file: " + filename );
            try {
            	smsDao.insertParsingResultAscii(parseResult,filename);
            }catch(SQLException s) {
            	lineError++;
            	SmsAppTools.InsertEventLog(SmsAppConstant.SQL_ERROR, s.getMessage()+"-"+filename, sourcePathId);
            }
        }
        catch ( IOException e )
        {
            logger.error( Thread.currentThread().getName() +e.getClass() + ": " + e.getMessage(), e );
        }
        // update end processing time
        try  {
        	SmsAppTools.updateFileStatus(filename, SmsAppConstant.FLAG_PARSE_DONE);
        }catch(SQLException s) {
        	logger.error(s);
        	SmsAppTools.InsertEventLog(SmsAppConstant.SQL_ERROR, s.getMessage(), sourcePathId);
        }
        
    }
    
    private static FixedLengthAsciiBean ParseToBean(String oneLine) {
     	if("".equals(oneLine) || oneLine == null) return null;
    	
    	
    	//
    	FixedLengthAsciiBean f = new FixedLengthAsciiBean();
    	int beginIndex=0;
    	int endIndex=0;
    	    	
    	for(int j=0;j<rule.size();j++) {

	    		FieldValueRuleBean fvb = (FieldValueRuleBean)rule.get(j);
	    		endIndex = endIndex + fvb.getValueRule();
	    		int len = endIndex;
	    		
	    		if(oneLine.length()==Integer.valueOf(bootParam.getParserProperties().getProperty("comptel.length")) || oneLine.length()==Integer.valueOf(bootParam.getParserProperties().getProperty("telepath.length"))) {
	    			if(len<=oneLine.length()) {
	    		
	    			switch(j) {
	    				case 0 : //recType
	    					f.setRecType(oneLine.substring(beginIndex, endIndex));
	    					break;
	    				case 1 : //structCode
	    					f.setStructCode(oneLine.substring(beginIndex, endIndex));
	    					break;
	    				case 2 : //clgNpi
							f.setClgNpi(oneLine.substring(beginIndex, endIndex));
							break;
	    				case 3 : //clgNumber
	    					f.setClgNumber(normalizePrefix(trimZeroPrefix(oneLine.substring(beginIndex, endIndex))));
	    					break;
	    				case 4 : //clgCustId
	    					f.setClgCustId(trimZeroPrefix(oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 5 : //cldNpi
	    					f.setCldNpi(oneLine.substring(beginIndex, endIndex));
	    					break;
	    				case 6 : //cldNumber
	    					f.setCldNumber(normalizePrefix(trimZeroPrefix(oneLine.substring(beginIndex, endIndex))));
	    					break;
	    				case 7 : //cldCustid
	    					f.setCldCustId(trimZeroPrefix(oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 8 : //msgSubTime
	    					f.setMsgSubTime(toDateString((String)oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 9 : //msgDlrTime
	    					f.setMsgDlrTime(toDateString((String)oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 10: //causTerm
	    					f.setCausTerm(oneLine.substring(beginIndex, endIndex));
	    					break;
	    				case 11: //callRef
	    					f.setCallRef(oneLine.substring(beginIndex, endIndex));
	    					break;
	    				case 12: //msgLength
	    					f.setMsgLength(trimZeroPrefix(oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 13: //priority
	    					f.setPriority(oneLine.substring(beginIndex, endIndex));
	    					break;
	    				case 14: //deferred
	    					f.setDeferred(oneLine.substring(beginIndex, endIndex));
	    					break;
	    				case 15: //receipt
	    					f.setReceipt(oneLine.substring(beginIndex, endIndex));
	    					break;
	    				case 16: //nbAttemp
	    					f.setNbAttempt(trimZeroPrefix(oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 17: //protId
	    					f.setProtId(oneLine.substring(beginIndex, endIndex));
	    					break;
	    				case 18: //clgMscFlag
	    					f.setClgMscFlag(oneLine.substring(beginIndex, endIndex));
	    					break;
	    				case 19: //clgMscGt
	    					f.setClgMscGt(trimZeroPrefix(oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 20: //cldMscFlag
	    					f.setCldMscFlag(oneLine.substring(beginIndex, endIndex));
	    					break;
	    				case 21: //cldMscGt
	    					f.setCldMscGt(trimZeroPrefix(oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 22: //mapError
	    					f.setMapError(trimSpaces(oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 23: //localError
	    					f.setLocalError(trimSpaces(oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 24: //msgState
	    					f.setMsgState(trimSpaces(oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 25: //msgStatus
	    					f.setMsgStatus(trimSpaces(oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 26: //clgImsi
	    					f.setClgImsi(trimZeroPrefix(oneLine.substring(beginIndex, endIndex)));
	    					break;
	    				case 27: //cldImsi
	    					f.setCldImsi(trimZeroPrefix(oneLine.substring(beginIndex, endIndex)));
	    					break;
	    			}
	    		   	
	    			//Object content = oneLine.substring(beginIndex, endIndex); 
	    			//
	    			//BeanUtils.setProperty(f, fvb.getNameRule(),content );
	    			
	    		beginIndex = endIndex;
    		}
	    			f.setClgFlag(flagging(f.getClgNumber()));
	    	    	f.setCldFlag(flagging(f.getCldNumber()));
	    	}    	
    	
    	//return normalizeAndFlagging(f);
    	}
    	return f;
    }
    
    
/*    private static FixedLengthAsciiBean normalizeAndFlagging(FixedLengthAsciiBean input) {
    	FixedLengthAsciiBean result = input;
    	// trim  clgNumber
    	input.setClgNumber(normalizePrefix(trimZeroPrefix(input.getClgNumber())));
    	input.setCldNumber(normalizePrefix(trimZeroPrefix(input.getCldNumber())));
    	input.setClgFlag(flagging(input.getClgNumber()));
    	input.setCldFlag(flagging(input.getCldNumber()));
    	
    	input.setCldCustId(trimZeroPrefix(input.getCldCustId()));
    	input.setClgCustId(trimZeroPrefix(input.getClgCustId()));
    	
    	input.setClgMscGt(trimZeroPrefix(input.getClgMscGt()));
    	input.setCldMscGt(trimZeroPrefix(input.getCldMscGt()));
    	input.setClgImsi(trimZeroPrefix(input.getClgImsi()));
    	input.setCldImsi(trimZeroPrefix(input.getCldImsi()));
    	input.setMsgLength(Long.valueOf(trimZeroPrefix(String.valueOf(input.getMsgLength()))).longValue());
    	input.setNbAttempt(Long.valueOf(trimZeroPrefix(String.valueOf(input.getNbAttempt()))).longValue());
    	
    	input.setMsgState(trimSpaces(String.valueOf(input.getMsgState())));
    	input.setMsgStatus(Long.valueOf(trimSpaces(String.valueOf(input.getMsgStatus()))).longValue());
    	
    	return result;
    }*/
    private static String trimZeroPrefix(String input) {
    	if(input==null ) return "0";
    	else if("".equals(input.trim())) return "0";
    	else if("0".equals(input)) return "0";
    	else 
    	return input.replaceAll("^0*", "");
    }
    private static String trimSpaces(String input) {
    	if(input==null ) return "";
    	else 
    	return input.replaceAll("^\\s*", "");
    }
    private static Date toDateString(String date) {
    	String dateStr = date.substring(0,date.length()-4);
    	SimpleDateFormat sdf = new SimpleDateFormat("yyMMddhhmmss");
    	try {
    		return sdf.parse(dateStr);
    	}catch(ParseException p) {
    		return null;
    	}
    }
    private static String flagging(String input) {
    	String result = "";
    	if(input==null||"".equals(input)) return "";
    	int len = input.length();
    	if(len<=6) {
    		result = SmsAppConstant.FLAG_MACHINE;
    	}else {
    		String prefix = input.substring(0,5);
    		result = bootParam.getFlaggingRuleProperties().getProperty(prefix);
    		if(result == null) {
    			result = SmsAppConstant.FLAG_EXT_OPERS;
    		}
    	}
    	return result;
    }
    private static String normalizePrefix(String input) {
    	String result = "";
    	if(input==null||"".equals(input)) return "";
    	else if(input.length()<4) return "";
    	
    	if(!input.substring(0,2).equals("62")) {
    		if(input.length()<=6) {
    			result = input;
    		}
    		else {
    			String temp = "62"+input.substring(0,3);
    			if(bootParam.getFlaggingRuleProperties().getProperty(temp)!=null) {
    				result = "62"+input;
    			}
    			else {
    				result = input;
    			}
    		}
    	}
    	else {
    		result = input;
    	}
    	
    	return result;
    }
}
